package com.cgy.utils.base.fusing;

import com.cgy.utils.base.fusing.handler.FusingHandler;
import com.cgy.utils.base.fusing.setting.FusingCommandSetting;
import com.cgy.utils.base.fusing.setting.FusingThreadPoolSetting;
import com.cgy.utils.base.fusing.setting.IFusingCommandHandler;
import com.cgy.utils.base.fusing.setting.IFusingThreadPoolHanlder;
import com.netflix.hystrix.*;

/**
 * 	熔断设置
 * @author CH
 *
 */
public abstract class FusingHystrix<T> extends HystrixCommand<T> implements IFusingCommandHandler, IFusingThreadPoolHanlder {

	protected static final String FUSING_DEFAULT_GROUP = "DefaultGroup";
	protected static final String FUSING_DEFAULT_THREAD_GROUP = "DefaultThreadGroup";
	
	public FusingHystrix(FusingHandler<T> iFusingHandler) {
		super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey(FUSING_DEFAULT_GROUP))
				.andCommandPropertiesDefaults(
						HystrixCommandProperties.Setter()
							.withRequestLogEnabled(false)
						)
				);
	}
	
	
	public FusingHystrix(FusingHandler<T> iFusingHandler, final FusingThreadPoolSetting fusingThreadPoolSetting) {
		super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey(FUSING_DEFAULT_GROUP))
				.andCommandKey(HystrixCommandKey.Factory.asKey(FUSING_DEFAULT_GROUP))
				.andThreadPoolKey(HystrixThreadPoolKey.Factory.asKey(FUSING_DEFAULT_THREAD_GROUP))
				.andCommandPropertiesDefaults(
						HystrixCommandProperties.Setter()
							.withRequestLogEnabled(false)
						)
				.andThreadPoolPropertiesDefaults(threadPool(fusingThreadPoolSetting)));
	}
	
	public FusingHystrix(FusingHandler<T> iFusingHandler, final FusingCommandSetting fusingCommandSetting) {
		super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey(FUSING_DEFAULT_GROUP))
				.andCommandKey(HystrixCommandKey.Factory.asKey(FUSING_DEFAULT_GROUP))
				.andCommandPropertiesDefaults(command(fusingCommandSetting))
				.andThreadPoolKey(HystrixThreadPoolKey.Factory.asKey(FUSING_DEFAULT_GROUP)));
	}


	public static com.netflix.hystrix.HystrixThreadPoolProperties.Setter threadPool(final FusingThreadPoolSetting fusingThreadPoolSetting) {
		com.netflix.hystrix.HystrixThreadPoolProperties.Setter setting = HystrixThreadPoolProperties.Setter();
		if(fusingThreadPoolSetting.getCoreSize() > 0) {
			setting.withCoreSize(fusingThreadPoolSetting.getCoreSize());
		} else {
			setting.withCoreSize(10);
		}
		if(fusingThreadPoolSetting.getKeepAliveTimeMinutes() > 0) {
			setting.withKeepAliveTimeMinutes(fusingThreadPoolSetting.getKeepAliveTimeMinutes());
		} else {
			setting.withKeepAliveTimeMinutes(1);
		}
		if(fusingThreadPoolSetting.getMaxQueueSize() > -2) {
			setting.withMaxQueueSize(fusingThreadPoolSetting.getMaxQueueSize());
		} else {
			setting.withMaxQueueSize(-1);
		}
		if(fusingThreadPoolSetting.getQueueSizeRejectionThreshold() > 0) {
			setting.withQueueSizeRejectionThreshold(fusingThreadPoolSetting.getQueueSizeRejectionThreshold());
		} else {
			setting.withQueueSizeRejectionThreshold(10);
		}
		if(fusingThreadPoolSetting.getRollingStatisticalWindowBuckets() > 0) {
			setting.withMetricsRollingStatisticalWindowBuckets(fusingThreadPoolSetting.getRollingStatisticalWindowBuckets());
		} else {
			setting.withMetricsRollingStatisticalWindowBuckets(10);
		}
		if(fusingThreadPoolSetting.getRollingStatisticalWindowInMilliseconds() > 0) {
			setting.withMetricsRollingStatisticalWindowInMilliseconds(fusingThreadPoolSetting.getRollingStatisticalWindowInMilliseconds());
		} else {
			setting.withMetricsRollingStatisticalWindowInMilliseconds(10 * 1000);
		}
		
		return setting;
	}


	public static com.netflix.hystrix.HystrixCommandProperties.Setter command(FusingCommandSetting commandSetting) {
		com.netflix.hystrix.HystrixCommandProperties.Setter setter = HystrixCommandProperties.Setter();

		if(null != commandSetting.getCircuitBreakerEnabled()) {
			setter.withCircuitBreakerEnabled(commandSetting.getCircuitBreakerEnabled());
		}
		
		if(null != commandSetting.getCircuitBreakerForceClosed()) {
			setter.withCircuitBreakerForceClosed(commandSetting.getCircuitBreakerForceClosed());
		}
		
		if(null != commandSetting.getCircuitBreakerForceOpen()) {
			setter.withCircuitBreakerForceOpen(commandSetting.getCircuitBreakerForceOpen());
		}
		if(null != commandSetting.getCircuitBreakerRequestVolumeThreshold()) {
			setter.withCircuitBreakerRequestVolumeThreshold(commandSetting.getCircuitBreakerRequestVolumeThreshold());
		}
		if(null != commandSetting.getCircuitBreakerSleepWindowInMilliseconds()) {
			setter.withCircuitBreakerSleepWindowInMilliseconds(commandSetting.getCircuitBreakerSleepWindowInMilliseconds());
		}
		if(null != commandSetting.getExecutionIsolationSemaphoreMaxConcurrentRequests()) {
			setter.withExecutionIsolationSemaphoreMaxConcurrentRequests(commandSetting.getExecutionIsolationSemaphoreMaxConcurrentRequests());
		}
		if(null != commandSetting.getExecutionIsolationStrategy()) {
			setter.withExecutionIsolationStrategy(commandSetting.getExecutionIsolationStrategy());
		}
		if(null != commandSetting.getFallbackEnabled()) {
			setter.withFallbackEnabled(commandSetting.getFallbackEnabled());
		}
		if(null != commandSetting.getFallbackIsolationSemaphoreMaxConcurrentRequests()) {
			setter.withFallbackIsolationSemaphoreMaxConcurrentRequests(commandSetting.getFallbackIsolationSemaphoreMaxConcurrentRequests());
		}
		if(null != commandSetting.getMetricsRollingPercentileEnabled()) {
			setter.withMetricsRollingPercentileEnabled(commandSetting.getMetricsRollingPercentileEnabled());
		}
		if(null != commandSetting.getRequestCacheEnabled()) {
			setter.withRequestCacheEnabled(commandSetting.getRequestCacheEnabled());
		}
		if(null != commandSetting.getRequestLogEnabled()) {
			setter.withRequestLogEnabled(commandSetting.getRequestLogEnabled());
		}

		if(null != commandSetting.getExecutionTimeoutInMilliseconds()) {
			setter.withExecutionTimeoutEnabled(true);
			setter.withExecutionTimeoutInMilliseconds(commandSetting.getExecutionTimeoutInMilliseconds());
		}


		return setter;
	}


	@Override
	public com.netflix.hystrix.HystrixThreadPoolProperties.Setter threadPoolProperties(
			FusingThreadPoolSetting fusingThreadPoolSetting) {
		return threadPool(fusingThreadPoolSetting);
	}


	@Override
	public com.netflix.hystrix.HystrixCommandProperties.Setter commandProperties(FusingCommandSetting commandSetting) {
		return command(commandSetting);
	}


}
